package com.xc.dsocket.server.x2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class Xx {
    private static final int TIMEOUT = 3000;
    private static final int BUF_SIZE=1024;


    public static void main(String[] args) {
        Xx xx = new Xx();
        xx.selector();
    }


    public void selector(){
        Selector selector = null;
        ServerSocketChannel ssc = null;

        try {
            selector = Selector.open();
            ssc= ServerSocketChannel.open();
            ssc.socket().bind(new InetSocketAddress(8083));
            ssc.configureBlocking(false);
            ssc.register(selector, SelectionKey.OP_ACCEPT);

            while (true){
                if(selector.select(TIMEOUT) == 0){
                    System.out.println("==");
                    continue;
                }
                Iterator<SelectionKey> iter  = selector.selectedKeys().iterator();
                while (iter.hasNext()){
                    SelectionKey key = iter.next();
                    if(key.isAcceptable()){
                        handleAccept(key);
                    }
                    if(key.isReadable()){
                        handleRead(key);
                    }
                    if(key.isWritable() && key.isValid()){
                        handleWrite(key);
                    }
                    if(key.isConnectable()){
                        System.out.println("isConnectable = true");
                    }
                    iter.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(selector != null){
                        selector.close();

                }
                if(ssc != null){
                    ssc.close();
                }
            } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }

    private void handleAccept(SelectionKey key){
        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
        SocketChannel accept = null;
        try {
            accept = channel.accept();
            accept.configureBlocking(false);
            channel.register(key.selector(),SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
        } catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }

    private void handleRead(SelectionKey key){
        SocketChannel  channel = (SocketChannel) key.channel();
        ByteBuffer buf = (ByteBuffer) key.attachment();
        try {
            long bytesRead = channel.read(buf);
            while (bytesRead > 0){
                buf.flip();
                while(buf.hasRemaining()){
                    System.out.print((char)buf.get());
                }
                System.out.println();
                buf.clear();
                bytesRead = channel.read(buf);
            }
            if(bytesRead == -1){
                channel.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void handleWrite(SelectionKey key){
        ByteBuffer buf = (ByteBuffer) key.attachment();
        buf.flip();
        SocketChannel sc = (SocketChannel) key.channel();
        while (buf.hasRemaining()){
            try {
                sc.write(buf);
                buf.compact();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
